package com.nova.bluetooth.base;

import android.graphics.Color;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.databinding.ObservableField;
import androidx.lifecycle.MutableLiveData;

import com.scwang.smart.refresh.layout.api.RefreshLayout;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.functions.Consumer;


public abstract class BaseNovaViewModel extends BaseViewModel implements OnNovaRefreshLoadMoreListener {


    private boolean isFirst;

    public BaseNovaViewModel() {
        super();
        //设置默认参数
        pageSize = 10;
        pageCurrent = 1;
        isNoMoreData.set(false);
        isRefreshAnim.setValue(false);
        enableLoadMore.set(true);
        enableRefresh.set(true);
        isNoEmptyData.set(false);
        isEmptyData.set(View.GONE);

        refreshStatus.setValue(RefreshStatus.None);
        mCommonList.setValue(new ArrayList());
        commonList.setValue(new ArrayList());
        showContentUi();
        isFirst = true;
        loadingBgColor.set(Color.parseColor("#00000000"));
        noNetworkBgColor.set(Color.parseColor("#00000000"));
    }

    public void setFirst(boolean first) {
        isFirst = first;
    }

    /**
     * 公共RecyclerView 数据
     */
    public MutableLiveData<List> commonList = new MutableLiveData<>();

    public ObservableField<Integer> isNetErr = new ObservableField<>();

    public ObservableField<Integer> isEmptyData = new ObservableField<>();

    public ObservableField<Integer> isLoading = new ObservableField<>();

    public ObservableField<Integer> loadingBgColor = new ObservableField<>();
    public ObservableField<Integer> noNetworkBgColor = new ObservableField<>();

    //EnableLoadMore 是否开启上拉刷新 加载更多
    public ObservableField<Boolean> enableLoadMore = new ObservableField<>();
    //EnableRefresh 是否开启下拉刷新
    public ObservableField<Boolean> enableRefresh = new ObservableField<>();
    //是否开启刷新动画
    public MutableLiveData<Boolean> isRefreshAnim = new MutableLiveData<>();
    //是否有更多数据
    public ObservableField<Boolean> isNoMoreData = new ObservableField<>();
    //状态显示页是否和 集合无关 而且 不显示无数据页面
    public ObservableField<Boolean> isNoEmptyData = new ObservableField<>();
    //刷新状态
    public MutableLiveData<RefreshStatus> refreshStatus = new MutableLiveData<>();

    public MutableLiveData<ResultStatus> resultStatus = new MutableLiveData<>();

    // 网路是否请求成功
    public MutableLiveData<Boolean> isRequestSuccess = new MutableLiveData<>();

    public enum ResultStatus {
        OnBeforeResult(1),
        OnResult(2),
        OnAfterFailure(3);
        public final int status;

        ResultStatus(int status) {
            this.status = status;
        }
    }

    //刷新状态
    public enum RefreshStatus {
        None(0, false, false),
        Refreshing(1, false, false),
        Loading(2, false, false),
        RefreshFinishErr(1, true, false),
        RefreshFinishSuccess(1, true, true),
        LoadFinishErr(2, true, false),
        LoadFinishSuccess(2, true, true);

        public final boolean isHeader;
        public final boolean isFooter;
        public final boolean isFinishing;//正在完成状态：RefreshFinish LoadFinish TwoLevelFinish
        public final boolean isSuceess;

        RefreshStatus(int role, boolean finishing, boolean isSuceess) {
            this.isHeader = role == 1;
            this.isFooter = role == 2;
            this.isFinishing = finishing;
            this.isSuceess = isSuceess;
        }
    }


    @Override
    protected void onCleared() {
        super.onCleared();
    }


    @Override
    public void onLoadMore(@NonNull RefreshLayout refreshLayout) {
        loadData(true);
    }

    @Override
    public void onRefresh(@NonNull RefreshLayout refreshLayout) {
        loadData(false);
    }

    private boolean isMore;
    protected int pageSize; //页码大小
    protected int pageCurrent; //当前页码

    public int getPageSize() {
        return pageSize;
    }

    public int getPageCurrent() {
        return pageCurrent;
    }

    public void setPageCurrent(int pageCurrent) {
        this.pageCurrent = pageCurrent;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    private long startTime, endTime;

    public void loadData(boolean isMore) {
        this.isMore = isMore;
        if (!isMore) {
            showLoadingUi();
            refreshStatus.setValue(RefreshStatus.Refreshing);
            pageCurrent = 1;
        } else {
            pageCurrent = pageCurrent + 1;
            refreshStatus.setValue(RefreshStatus.Loading);
        }
        getPageData(pageCurrent);
    }

    /**
     * 子类需要super 此方法
     *
     * @param pageCurrent
     */
    public void getPageData(int pageCurrent) {
        startTime = System.currentTimeMillis();
    }


    public MutableLiveData<List> mCommonList = new MutableLiveData<>();

    public void setCommonList(List mDatas) {
        if (mDatas == null) {
            onDataFail();
            return;
        }
        if (!isMore) {
            if (mDatas == null || mDatas.size() == 0) {
                isNoMoreData.set(true);
            }else {
                isNoMoreData.set(false);
            }
            mCommonList.getValue().clear();
            List value = mCommonList.getValue();
            value.addAll(mDatas);
            if (isFirst) {
                refreshLoadingSuccess();
            } else {
                refreshFinishSuccess();
            }
        } else {
            if (mDatas == null || mDatas.size() == 0) {
                isNoMoreData.set(true);
            }else {
                isNoMoreData.set(false);
            }
            List value = mCommonList.getValue();
            value.addAll(mDatas);
            initData();
            loadFinishSuccess();
        }
    }

    private int refreshDuration = 500; //动画执行时间  500 - 30000  即 0.5s-30s 30s 网络请求超时时间
    private int loadMoreDuration = 500;//动画执行时间  500 - 30000  即 0.5s-30s 30s 网络请求超时时间 要不要单独加一个加载更多的动画时长
    private int loadingDuration = 500;//动画执行时间  500 - 30000  即 0.5s-30s 30s 网络请求超时时间

    public void refreshFinishSuccess() {
        isFirst = false;
        endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        if (duration > refreshDuration) {
            logTime();
            initData();
            showStatusUi();
            refreshStatus.setValue(RefreshStatus.RefreshFinishSuccess);
        } else {
            duration = refreshDuration - duration;
            Disposable disposable = Observable.just(1).delay(duration, TimeUnit.MILLISECONDS)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe((Consumer<Object>) o -> {
                        logTime();
                        initData();
                        showStatusUi();
                        refreshStatus.setValue(RefreshStatus.RefreshFinishSuccess);
                    });
            register(disposable);
        }
    }

    public void loadFinishSuccess() {
        endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        if (duration > loadMoreDuration) {
            logTime();
            refreshStatus.setValue(RefreshStatus.LoadFinishSuccess);
        } else {
            duration = loadMoreDuration - duration;
            Disposable disposable = Observable.just(1).delay(duration, TimeUnit.MILLISECONDS)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe((Consumer<Object>) o -> {
                        logTime();
                        refreshStatus.setValue(RefreshStatus.LoadFinishSuccess);
                    });
            register(disposable);
        }
    }



    private void initData() {
        commonList.setValue(mCommonList.getValue());
    }

    private void refreshLoadingSuccess() {
        isFirst = false;
        endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        if (duration > loadingDuration) {
            logTime();
            initData();
            showStatusUi();
        } else {
            duration = loadingDuration - duration;
            Disposable disposable = Observable.just(1).delay(duration, TimeUnit.MILLISECONDS)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe((Consumer<Object>) o -> {
                        logTime();
                        initData();
                        showStatusUi();
                    });
            register(disposable);
        }
    }

    private void showStatusUi() {
        if(isNoEmptyData.get()){
            showContentUi();
        }else {
            if (commonList.getValue().size() > 0) {
                showContentUi();
            } else {
                showEmptyUi();
            }
        }
    }


    public void logTime() {
        endTime = System.currentTimeMillis();
//        KLog.d("startTime = " + startTime);
//        KLog.d("endTime = " + endTime);
        long duration = endTime - startTime;
//        KLog.d("duration = " + duration);
    }


    public void onDataFail() {
        if (!isMore) {
            if (isFirst) {
                refreshLoadingErr();
            } else {
                refreshFinishErr();
            }
        } else {
            loadFinishErr();
        }
    }

    private void refreshLoadingErr() {
        isFirst = false;
        endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        if (duration > loadingDuration) {
            logTime();
            showNetErrUi();
            refreshStatus.setValue(RefreshStatus.RefreshFinishErr);
        } else {
            duration = loadingDuration - duration;
            Disposable disposable = Observable.just(1).delay(duration, TimeUnit.MILLISECONDS)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe((Consumer<Object>) o -> {
                        logTime();
                        showNetErrUi();
                        refreshStatus.setValue(RefreshStatus.RefreshFinishErr);
                    });
            register(disposable);
        }
    }

    public void refreshFinishErr() {
        endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        if (duration > refreshDuration) {
            logTime();
            showNetErrUi();
            refreshStatus.setValue(RefreshStatus.RefreshFinishErr);
        } else {
            duration = refreshDuration - duration;
            Disposable disposable = Observable.just(1).delay(duration, TimeUnit.MILLISECONDS)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe((Consumer<Object>) o -> {
                        logTime();
                        showNetErrUi();
                        refreshStatus.setValue(RefreshStatus.RefreshFinishErr);
                    });
            register(disposable);
        }
    }

    public void loadFinishErr() {
        endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        if (duration > loadMoreDuration) {
            logTime();
            showNetErrUi();
            refreshStatus.setValue(RefreshStatus.LoadFinishErr);
        } else {
            duration = loadMoreDuration - duration;
            Disposable disposable = Observable.just(1).delay(duration, TimeUnit.MILLISECONDS)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe((Consumer<Object>) o -> {
                        logTime();
                        showNetErrUi();
                        refreshStatus.setValue(RefreshStatus.LoadFinishErr);
                    });
            register(disposable);
        }
    }


    public void showNetErrUi() {
        isNetErr.set(View.VISIBLE);
        isEmptyData.set(View.GONE);
        isLoading.set(View.GONE);
    }

    public void showContentUi() {
        isNetErr.set(View.GONE);
        isEmptyData.set(View.GONE);
        isLoading.set(View.GONE);
    }

    public void showEmptyUi() {
        isEmptyData.set(View.VISIBLE);
        isNetErr.set(View.GONE);
        isLoading.set(View.GONE);
    }

    public void showLoadingUi() {
        if (isFirst) {
            isEmptyData.set(View.GONE);
            isNetErr.set(View.GONE);
            isLoading.set(View.VISIBLE);
        }
    }



}
